home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / board / Chaos53src.lha / chaos / src / Out.c < prev    next >
C/C++ Source or Header  |  1994-12-03  |  31KB  |  1,241 lines

  1. /*  Chaos:            The Chess HAppening Organisation System    V5.3
  2.     Copyright (C)   1993    Jochen Wiedmann
  3.  
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 2 of the License, or
  7.     (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18.  
  19.     $RCSfile: Out.c,v $
  20.     $Revision: 3.4 $
  21.     $Date: 1994/12/03 18:02:26 $
  22.  
  23.     This file contains most of the output-functions.
  24.  
  25.     Computer:    Amiga 1200            Compiler:    Dice 2.07.54 (3.0)
  26.  
  27.     Author:    Jochen Wiedmann
  28.         Am Eisteich 9
  29.       72555 Metzingen
  30.         Tel. 07123 / 14881
  31.         Internet: wiedmann@mailserv.zdv.uni-tuebingen.de
  32. */
  33.  
  34.  
  35. #ifndef CHAOS_H
  36. #include "chaos.h"
  37. #endif
  38.  
  39.  
  40.  
  41.  
  42. /*
  43.     PointsToA() creates a string holding the number of points from p.
  44.  
  45.     Inputs: s - the string where the result should be written
  46.         p - the number of points
  47. */
  48. void PointsToA(char *s, long p)
  49.  
  50. { if (WinnerPoints%2  ||  DrawPoints%2)
  51.   { sprintf(s, "%ld%s", p/2, (p%2)?".5":"  ");
  52.   }
  53.   else
  54.   { sprintf(s, "%ld", p/2);
  55.   }
  56. }
  57.  
  58.  
  59.  
  60.  
  61. /*
  62.     tdwz() returns the DW (German rating number) of a player as short.
  63. */
  64. int tdwz(struct Player *t)
  65.  
  66. { long dwz;
  67.  
  68. #ifdef AMIGA
  69.   if (StrToLong((STRPTR) t->DWZ, &dwz) < 0)
  70.   { dwz = 0;
  71.   }
  72. #else
  73.   dwz = atol(t->DWZ);
  74. #endif
  75.   return ((short) dwz);
  76. }
  77.  
  78.  
  79.  
  80.  
  81. /*
  82.     RatingToA() gets a string from a DWZ or ELO number.
  83.  
  84.     Inputs: s - the string, that should be written
  85.         w - the rating number (Note, that this must not be the
  86.         Player->DWZ field itself, because this is a string!)
  87. */
  88. static void RatingToA(char *s, int w)
  89.  
  90. { if(w == 0)
  91.   { *s = '\0';
  92.   }
  93.   else
  94.   { sprintf(s, "%d", w);
  95.   }
  96. }
  97.  
  98.  
  99.  
  100.  
  101. /*
  102.     lprint() is used to buffer the output which will be done later with
  103.     ProcessOutput(). It can work in two modes: The first is building a list
  104.     of lines, the second is collecting ALL lines in a single string.
  105.     The latter is needed on the Amiga for using a FloatText gadget while the
  106.     list is needed for output on the printer.
  107.  
  108.     Inputs: line - the string holding the line
  109.  
  110.     Result: TRUE, if successfull, FALSE otherwise
  111. */
  112. int lprint(char *line)
  113.  
  114. { extern struct MinList OutputList;
  115.   extern void *OutputMemList;
  116.   extern int OutputLineLen, OutputLineMaxLen;
  117.   extern char*OutputLine;
  118.   extern int OutputReturnCode;
  119.   struct MinNode *n;
  120.   char *ptr;
  121.   int i, len;
  122.  
  123.   /*
  124.       Get length of string, ignore trailing blanks.
  125.   */
  126.   for (i = 1, len = 0, ptr = line;  *ptr != '\0';  ptr++, i++)
  127.   { if (*ptr != ' ')
  128.     { len = i;
  129.     }
  130.   }
  131.  
  132.   if (OutputLineMaxLen == -1)
  133.   { if ((n = GetMem(&OutputMemList, sizeof(*n)+len+1))  ==  NULL)
  134.     { OutputReturnCode = RETURN_ERROR;
  135.       return(FALSE);
  136.     }
  137.  
  138.     strncpy((char *) (n+1), line, len);
  139.     ((char *) (n+1))[len] = '\0';
  140.     AddTail((struct List *) &OutputList, (struct Node *) n);
  141.   }
  142.   else
  143.   { while (OutputLineLen + len + 2  >  OutputLineMaxLen)
  144.     { if ((ptr = GetMem(&OutputMemList, OutputLineMaxLen += 16384))  ==  NULL)
  145.       { OutputReturnCode = RETURN_ERROR;
  146.     return(FALSE);
  147.       }
  148.       if (OutputLine != NULL)
  149.       { strcpy(ptr, OutputLine);
  150.     PutMem(OutputLine);
  151.       }
  152.       OutputLine = ptr;
  153.     }
  154.  
  155.     strncpy(OutputLine+OutputLineLen, line, len);
  156.     OutputLine[OutputLineLen += len] = '\n';
  157.     OutputLine[++OutputLineLen] = '\0';
  158.   }
  159.   return(TRUE);
  160. }
  161.  
  162.  
  163.  
  164.  
  165. /*
  166.     longlprint() does the same job as lprint(), but can process text with
  167.     more than one line. The lines are split and lprint is called for each
  168.     line.
  169.  
  170.     Inputs: txt - the string holding the text; note, that a single line must
  171.           not extend 512 characters!
  172.  
  173.     Result: TRUE, if successfull, FALSE otherwise
  174. */
  175. int longlprint(char *txt)
  176.  
  177. { char line[512];
  178.   char *lptr;
  179.   char c;
  180.  
  181.   while (*txt != '\0')
  182.   { lptr = line;
  183.     while ((c = *txt) != '\0'  &&  c != '\n')
  184.     { *(lptr++) = *(txt++);
  185.     }
  186.     *lptr = '\0';
  187.     if (!lprint(line))
  188.     { return(FALSE);
  189.     }
  190.     if (c == '\n')
  191.     { txt++;
  192.     }
  193.   }
  194.   return(TRUE);
  195. }
  196.  
  197.  
  198.  
  199.  
  200. /*
  201.     This function prints the list of players.
  202.  
  203.     Inputs: filename    - destination file; see InitOutput()
  204.         device    - device; see InitOutput()
  205.         longformat    - TRUE, if long format, FALSE otherwise
  206. */
  207. void OutPlayerList(char *filename, int device, int longformat)
  208.  
  209. { struct Player *t;
  210.   int i, lines;
  211.   char head[301];
  212.   char line1[121], line2[121], line3[121];
  213.   char dwz[6], elo[6];
  214.  
  215.   if (longformat == FALSE)
  216.   { lines = 1;
  217.     sprintf(head, "%-4s %-30s %6s %6s %s",
  218.         GetChaosString(MSG_NUMBER),
  219.         GetChaosString(MSG_NAME_OUTPUT),
  220.         GetChaosString(MSG_DWZ_OUTPUT),
  221.         GetChaosString(MSG_ELO_OUTPUT),
  222.         GetChaosString(MSG_CHESSCLUB_OUTPUT));
  223.   }
  224.   else
  225.   { lines = 4;
  226.     sprintf(head, "%-4s %-30s %-30s %s\n"
  227.           "     %-30s %-30s %s\n"
  228.           "     %-15s %s%s%s %s%s%s%s%s      %s\n",
  229.         GetChaosString(MSG_NUMBER),
  230.         GetChaosString(MSG_NAME_OUTPUT),
  231.         GetChaosString(MSG_STREET_OUTPUT),
  232.         GetChaosString(MSG_DWZ_OUTPUT),
  233.  
  234.         GetChaosString(MSG_CHESSCLUB_OUTPUT),
  235.         GetChaosString(MSG_VILLAGE_OUTPUT),
  236.         GetChaosString(MSG_ELO_OUTPUT),
  237.  
  238.         GetChaosString(MSG_BIRTHDAY_OUTPUT),
  239.         GetChaosString(MSG_SENIOR_SHORT),
  240.         GetChaosString(MSG_JUNIOR_SHORT),
  241.         GetChaosString(MSG_WOMAN_SHORT),
  242.         GetChaosString(MSG_JUNIORA_SHORT),
  243.         GetChaosString(MSG_JUNIORB_SHORT),
  244.         GetChaosString(MSG_JUNIORC_SHORT),
  245.         GetChaosString(MSG_JUNIORD_SHORT),
  246.         GetChaosString(MSG_JUNIORE_SHORT),
  247.         GetChaosString(MSG_PHONE_OUTPUT));
  248.   }
  249.   if (!InitOutput((char *) GetChaosString(MSG_PLAYER_LIST_TITLE),
  250.           head, head, filename, "#?.plst", device, lines, lines))
  251.   { TerminateOutput();
  252.     return;
  253.   }
  254.  
  255.   for (t = (struct Player *) PlayerList.lh_Head, i = 1;
  256.        t->Tn_Node.ln_Succ != NULL;
  257.        t = (struct Player *) t->Tn_Node.ln_Succ, i++)
  258.   { RatingToA(dwz, tdwz(t));
  259.     RatingToA(elo, (int) t->ELO);
  260.  
  261.     if (!longformat)
  262.     { sprintf(line1, "%-4d %-30s %6s %6s %-30s", i, t->Name, dwz, elo,
  263.           t->ChessClub);
  264.       if (!lprint(line1))
  265.       { TerminateOutput();
  266.     return;
  267.       }
  268.     }
  269.     else
  270.     { sprintf(line1, "%-4d %-30s %-30s %s", i, t->Name, t->Street, dwz);
  271.       sprintf(line2, "     %-30s %-30s %s", t->ChessClub, t->Village, elo);
  272.       sprintf(line3, "     %-15s %s%s%s %s%s%s%s%s      %s",
  273.           t->BirthDay,
  274.           (t->Flags & TNFLAGSF_SENIOR)   ?
  275.             (char *) GetChaosString(MSG_SENIOR_SHORT)  : " ",
  276.           (t->Flags & TNFLAGSF_JUNIOR)   ?
  277.             (char *) GetChaosString(MSG_JUNIOR_SHORT)  : " ",
  278.           (t->Flags & TNFLAGSF_WOMAN)     ?
  279.             (char *) GetChaosString(MSG_WOMAN_SHORT)   : " ",
  280.           (t->Flags & TNFLAGSF_JUNIORA)  ?
  281.             (char *) GetChaosString(MSG_JUNIORA_SHORT) : " ",
  282.           (t->Flags & TNFLAGSF_JUNIORB)  ?
  283.             (char *) GetChaosString(MSG_JUNIORB_SHORT) : " ",
  284.           (t->Flags & TNFLAGSF_JUNIORC)  ?
  285.             (char *) GetChaosString(MSG_JUNIORC_SHORT) : " ",
  286.           (t->Flags & TNFLAGSF_JUNIORD)  ?
  287.             (char *) GetChaosString(MSG_JUNIORD_SHORT) : " ",
  288.           (t->Flags & TNFLAGSF_JUNIORE)  ?
  289.             (char *) GetChaosString(MSG_JUNIORE_SHORT) : " ",
  290.           t->PhoneNr);
  291.  
  292.       if (!lprint(line1)  ||  !lprint(line2)  ||
  293.       !lprint(line3)  ||  !lprint(""))
  294.       { TerminateOutput();
  295.     return;
  296.       }
  297.     }
  298.   }
  299.  
  300.   ProcessOutput();
  301.   TerminateOutput();
  302. }
  303.  
  304.  
  305.  
  306.  
  307. /*
  308.     This function prints the results of one round.
  309.  
  310.     Inputs: filename    - destination file; see InitOutput()
  311.         device    - output device; see InitOutput()
  312.         Round    - number of the round, that should be printed
  313. */
  314. void OutRound(char *filename, int device, int Round)
  315.  
  316. { void *memlist;
  317.   struct MinList *rlist;
  318.   struct GameNode *gn;
  319.   char head[81];
  320.   char title[81];
  321.  
  322.   if ((rlist = GetRound(&memlist, Round, TRUE,
  323.             (device == DEVICE_Screen) ? 0 : 1))
  324.          ==  NULL)
  325.   { return;
  326.   }
  327.  
  328.   sprintf(head, "%4s %-30s:%-30s %s",
  329.       GetChaosString(MSG_NUMBER),
  330.       GetChaosString(MSG_WHITE_OUTPUT),
  331.       GetChaosString(MSG_BLACK_OUTPUT),
  332.       GetChaosString(MSG_RESULT_OUTPUT));
  333.   sprintf(title, (char *) GetChaosString(MSG_ROUND_TITLE), Round);
  334.   if (!InitOutput(title, head, head, filename, "#?.rslt", device, 1, 1))
  335.   { goto Terminate;
  336.   }
  337.  
  338.   for(gn = (struct GameNode *) rlist->mlh_Head;
  339.       gn->gn_Node.mln_Succ != NULL;
  340.       gn = (struct GameNode *) gn->gn_Node.mln_Succ)
  341.   { if (!lprint(gn->Text))
  342.     { goto Terminate;
  343.     }
  344.   }
  345.  
  346.   ProcessOutput();
  347.  
  348. Terminate:
  349.   TerminateOutput();
  350.   PutMemList(&memlist);
  351. }
  352.  
  353.  
  354.  
  355.  
  356. /*
  357.     This function creates the table. The players are connected via the
  358.     Player->Helpptr field.
  359.  
  360.     Inputs: sortmode    - sorting mode, either 0 (simple mode) or one of the
  361.               flags TNMODEF_BUCHHOLZ, TNMODEF_EXT_BUCHHOLZ or
  362.               TNMODEF_SONNEBORN_BERGER
  363.  
  364.     Result: pointer to the best player in the table
  365. */
  366. struct Player *MakeTable(int sortmode)
  367.  
  368. { struct Player *t, **tptr, *TabFirst;
  369.   struct Game *g;
  370.  
  371.   for (t = (struct Player *) PlayerList.lh_Head;
  372.        t->Tn_Node.ln_Succ != NULL;
  373.        t = (struct Player *) t->Tn_Node.ln_Succ)
  374.   { t->Buchholz = t->ExtBuchholz = 0;
  375.   }
  376.  
  377.   /*
  378.       Getting the Buchholz points
  379.   */
  380.   if (sortmode & (TNMODEF_BUCHHOLZ|TNMODEF_EXT_BUCHHOLZ))
  381.   { for (t = (struct Player *) PlayerList.lh_Head;
  382.      t->Tn_Node.ln_Succ != NULL;
  383.      t = (struct Player *) t->Tn_Node.ln_Succ)
  384.     { for (g = t->First_Game;  g != NULL;  g = g->Next)
  385.       { if ((g->Flags & GMFLAGSF_POINTFORFREE)  ==  0  &&
  386.         (g->Flags & GMFLAGSF_WITHDRAWN) == 0)
  387.     { t->Buchholz += g->Opponent->Points;
  388.     }
  389.       }
  390.     }
  391.  
  392.   /*
  393.       Getting the extended Buchholz points
  394.   */
  395.     if (sortmode & TNMODEF_EXT_BUCHHOLZ)
  396.     { for (t = (struct Player *) PlayerList.lh_Head;
  397.        t->Tn_Node.ln_Succ != NULL;
  398.        t = (struct Player *) t->Tn_Node.ln_Succ)
  399.       { for (g = t->First_Game;  g != NULL;  g = g->Next)
  400.     { if ((g->Flags & GMFLAGSF_POINTFORFREE)  ==  0  &&
  401.           (g->Flags & GMFLAGSF_WITHDRAWN) == 0)
  402.       { t->ExtBuchholz += g->Opponent->Buchholz;
  403.       }
  404.     }
  405.       }
  406.     }
  407.   }
  408.   /*
  409.       Getting the Sooneborn-Berger points
  410.   */
  411.   else if (sortmode & TNMODEF_SONNEBORN_BERGER)
  412.   { for (t = (struct Player *) PlayerList.lh_Head;
  413.      t->Tn_Node.ln_Succ != NULL;
  414.      t = (struct Player *) t->Tn_Node.ln_Succ)
  415.     { for (g = t->First_Game;  g != NULL;  g = g->Next)
  416.       { if ((g->Flags & GMFLAGSF_POINTFORFREE) == 0  &&
  417.         g->Result != -1)
  418.     { t->Buchholz += g->Opponent->Points * g->Result;
  419.     }
  420.       }
  421.     }
  422.   }
  423.  
  424.   /*
  425.       Sorting
  426.   */
  427.   TabFirst = NULL;
  428.   for (t = (struct Player *) PlayerList.lh_Head;
  429.        t->Tn_Node.ln_Succ != NULL;
  430.        t = (struct Player *) t->Tn_Node.ln_Succ)
  431.   { for (tptr = &TabFirst;  *tptr != NULL;
  432.      tptr = (struct Player **) &((*tptr)->Helpptr))
  433.     { if (t->Points > (*tptr)->Points  ||
  434.       (t->Points == (*tptr)->Points  &&
  435.        (t->Buchholz > (*tptr)->Buchholz  ||
  436.         (t->Buchholz == (*tptr)->Buchholz  &&
  437.          t->ExtBuchholz > (*tptr)->ExtBuchholz))))
  438.       { break;
  439.       }
  440.     }
  441.     t->Helpptr = *tptr;
  442.     *tptr = t;
  443.   }
  444.   return(TabFirst);
  445. }
  446.  
  447.  
  448.  
  449.  
  450. /*
  451.     The following function prints the table.
  452.  
  453.     Inputs: filename    - destination file; see InitOutput()
  454.         device    - output device; see InitOutput()
  455.         plrmode    - tells which players to include into the table:
  456.               Either 0 for all players or one of the flags
  457.               TNFLAGSF_SENIOR, TNFLAGSF_JUNIOR, TNFLAGSF_WOMAN,
  458.               TNFLAGSF_JUNIORA, TNFLAGSF_JUNIORB,
  459.               TNFLAGSF_JUNIORC, TNFLAGSF_JUNIORD or
  460.               TNFLAGSF_JUNIORE
  461.         sortmode    - tells how to sort the table; see MakeTable()
  462. */
  463. void OutTable(char *filename, int device, int plrmode, int sortmode)
  464.  
  465. { struct Player *t, *TabFirst;
  466.   int i, Place;
  467.   long pextbuchholz;
  468.   short ppoints, pbuchholz;
  469.   char head[81];
  470.   char line[81];
  471.   char title[81];
  472.   char subtitle[81];
  473.   char ppointsstrtr[10], pbuchholzstr[10], pextbuchholzstr[10];
  474.  
  475.   TabFirst = MakeTable(sortmode);
  476.  
  477.   switch (sortmode & TNMODE_TABMASK)
  478.   { case TNMODEF_BUCHHOLZ:
  479.       sprintf(head, "%-5s %-6s %-8s %-30s", GetChaosString(MSG_PLACE_OUTPUT),
  480.           GetChaosString(MSG_POINTS_OUTPUT),
  481.           GetChaosString(MSG_BUCHHOLZ_OUTPUT),
  482.           GetChaosString(MSG_NAME_OUTPUT));
  483.       break;
  484.     case TNMODEF_EXT_BUCHHOLZ:
  485.       sprintf(head, "%-5s %-6s %-8s %-9s %-30s",
  486.           GetChaosString(MSG_PLACE_OUTPUT),
  487.           GetChaosString(MSG_POINTS_OUTPUT),
  488.           GetChaosString(MSG_BUCHHOLZ_OUTPUT),
  489.           GetChaosString(MSG_EXT_BUCHHOLZ_OUTPUT),
  490.           GetChaosString(MSG_NAME_OUTPUT));
  491.       break;
  492.     case TNMODEF_SONNEBORN_BERGER:
  493.       sprintf(head, "%-5s %-6s %-8s %-30s", GetChaosString(MSG_PLACE_OUTPUT),
  494.           GetChaosString(MSG_POINTS_OUTPUT),
  495.           GetChaosString(MSG_SONNEBORN_BERGER_OUTPUT),
  496.           GetChaosString(MSG_NAME_OUTPUT));
  497.       break;
  498.     default:
  499.       sprintf(head, "%5s %6s %-30s", GetChaosString(MSG_PLACE_OUTPUT),
  500.           GetChaosString(MSG_POINTS_OUTPUT),
  501.           GetChaosString(MSG_NAME_OUTPUT));
  502.   }
  503.  
  504.   switch (plrmode)
  505.   { case TNFLAGSF_SENIOR:
  506.       sprintf(subtitle, "  -  %s",
  507.           GetChaosString(MSG_OUTPUT_TABLE_SENIORS_SUB));
  508.       break;
  509.     case TNFLAGSF_JUNIOR:
  510.       sprintf(subtitle, "  -  %s",
  511.           GetChaosString(MSG_OUTPUT_TABLE_JUNIORS_SUB));
  512.       break;
  513.     case TNFLAGSF_WOMAN:
  514.       sprintf(subtitle, "  -  %s",
  515.           GetChaosString(MSG_OUTPUT_TABLE_WOMEN_SUB));
  516.       break;
  517.     case TNFLAGSF_JUNIORA:
  518.       sprintf(subtitle, "  -  %s",
  519.           GetChaosString(MSG_OUTPUT_TABLE_JUNIORSA_SUB));
  520.       break;
  521.     case TNFLAGSF_JUNIORB:
  522.       sprintf(subtitle, "  -  %s",
  523.           GetChaosString(MSG_OUTPUT_TABLE_JUNIORSB_SUB));
  524.       break;
  525.     case TNFLAGSF_JUNIORC:
  526.       sprintf(subtitle, "  -  %s",
  527.           GetChaosString(MSG_OUTPUT_TABLE_JUNIORSC_SUB));
  528.       break;
  529.     case TNFLAGSF_JUNIORD:
  530.       sprintf(subtitle, "  -  %s",
  531.           GetChaosString(MSG_OUTPUT_TABLE_JUNIORSD_SUB));
  532.       break;
  533.     case TNFLAGSF_JUNIORE:
  534.       sprintf(subtitle, "  -  %s",
  535.           GetChaosString(MSG_OUTPUT_TABLE_JUNIORSE_SUB));
  536.       break;
  537.     default:
  538.       sprintf(subtitle, "");
  539.       break;
  540.   }
  541.   if (sortmode & TNMODEF_SWISS_PAIRING)
  542.   { sprintf(title, (char *) GetChaosString(MSG_TABLE_TITLE),
  543.         (NumGamesMissing == 0) ? NumRounds : NumRounds-1,
  544.         subtitle);
  545.   }
  546.   else
  547.   { sprintf(title, (char *) GetChaosString(MSG_TABLE_TITLE2), subtitle);
  548.   }
  549.  
  550.  
  551.   if (!InitOutput(title, head, head, filename, "#?.tbl", device, 1, 1))
  552.   { TerminateOutput();
  553.     return;
  554.   }
  555.  
  556.   /*
  557.       Force initialization of ppoints, pbucholz and pextbuchholz in the
  558.       following loop.
  559.   */
  560.   ppoints = -1;
  561.  
  562.   for (i = 0, t = TabFirst;  t != NULL;  t = t->Helpptr)
  563.   { if (plrmode != 0  &&  (plrmode & t->Flags) == 0)
  564.     { continue;
  565.     }
  566.     i++;
  567.     if (ppoints != t->Points  ||  pbuchholz != t->Buchholz  ||
  568.     pextbuchholz != t->ExtBuchholz)
  569.     { Place = i;
  570.       ppoints = t->Points;
  571.       pbuchholz = t->Buchholz;
  572.       pextbuchholz = t->ExtBuchholz;
  573.     }
  574.  
  575.     PointsToA(ppointsstrtr, (long) ppoints);
  576.     PointsToA(pbuchholzstr, (long) pbuchholz);
  577.     PointsToA(pextbuchholzstr, pextbuchholz);
  578.     switch (sortmode & TNMODE_TABMASK)
  579.       { case TNMODEF_BUCHHOLZ:
  580.     case TNMODEF_SONNEBORN_BERGER:
  581.       sprintf(line, "%5d %6s %8s %s", Place, ppointsstrtr, pbuchholzstr,
  582.           t->Name);
  583.       break;
  584.     case TNMODEF_EXT_BUCHHOLZ:
  585.       sprintf(line, "%5d %6s %8s %8s  %s", Place, ppointsstrtr,
  586.           pbuchholzstr, pextbuchholzstr, t->Name);
  587.       break;
  588.     default:
  589.       sprintf(line, "%5d %6s %s", Place, ppointsstrtr, t->Name);
  590.       }
  591.  
  592.     if (!lprint(line))
  593.     { TerminateOutput();
  594.       return;
  595.     }
  596.   }
  597.  
  598.   ProcessOutput();
  599.   TerminateOutput();
  600. }
  601.  
  602.  
  603.  
  604.  
  605. /*
  606.     The following function prints the internal ranking list.
  607.  
  608.     Inputs: filename    - destination file; see InitOutput()
  609.         device    - output device; see InitOutput()
  610. */
  611. void OutInternalRankings(char *filename, int device)
  612.  
  613. { struct Player *t;
  614.   int i;
  615.   char head[81], line[81], title[81];
  616.   char pointsstr[10];
  617.   char dwz[6], elo[6];
  618.  
  619.   if (NumRounds == 0  ||  RoundRobinTournament)
  620.   { sprintf(title, (char *) GetChaosString(MSG_RANKINGS_TITLE));
  621.     sprintf(head, "%-4s %-6s %-6s %-30s", GetChaosString(MSG_NUMBER),
  622.         GetChaosString(MSG_DWZ_OUTPUT), GetChaosString(MSG_ELO_OUTPUT),
  623.         GetChaosString(MSG_NAME_OUTPUT));
  624.     CreateRankings();
  625.   }
  626.   else
  627.   { sprintf(title, (char *) GetChaosString(MSG_RANKINGS_TITLE2),
  628.         NumRounds);
  629.     sprintf(head, "%-4s %-6s %-6s %-6s %-30s", GetChaosString(MSG_NUMBER),
  630.         GetChaosString(MSG_DWZ_OUTPUT), GetChaosString(MSG_ELO_OUTPUT),
  631.         GetChaosString(MSG_POINTS_OUTPUT), GetChaosString(MSG_NAME_OUTPUT));
  632.   }
  633.  
  634.   if (!InitOutput(title, head, head, filename, "#?.rnk", device, 1, 1))
  635.   { TerminateOutput();
  636.     return;
  637.   }
  638.  
  639.   for (t = RankingFirst, i = 0;  t != NULL;  t = t->RankNext)
  640.   { RatingToA(dwz, tdwz(t));
  641.     RatingToA(elo, (int) t->ELO);
  642.     if (NumRounds != 0)
  643.     { PointsToA(pointsstr, (long) t->Points);
  644.       sprintf(line, "%-4d %-6s %-6s %-5s  %s", ++i, dwz, elo,
  645.           pointsstr, t->Name);
  646.     }
  647.     else
  648.     { sprintf(line, "%-4d %-6s %-6s %s", ++i, dwz, elo, t->Name);
  649.     }
  650.     if (!lprint(line))
  651.     { TerminateOutput();
  652.       return;
  653.     }
  654.   }
  655.  
  656.   ProcessOutput();
  657.   TerminateOutput();
  658. }
  659.  
  660.  
  661.  
  662.  
  663. /*
  664.     The following function prints the table of progress.
  665.  
  666.     Inputs: filename    - destination file; see InitOutput()
  667.         device    - output device; see InitOutput()
  668.         sortmode    - sorting mode of the table; see MakeTable()
  669. */
  670. void OutTableProgress(char *filename, int device, int sortmode)
  671.  
  672. { struct Player *TabFirst, *t;
  673.   struct Game *g;
  674.   int i, gperline, needprint;
  675.   int lines;
  676.   char head[81], title[81], line[81], pointsstr[10], helps[10];
  677.  
  678.   sprintf(title, (char *) GetChaosString(MSG_PROGRESS_TABLE_TITLE),
  679.       NumRounds);
  680.   sprintf(head, "%-4s %-6s %-33s %s", GetChaosString(MSG_NUMBER),
  681.       GetChaosString(MSG_POINTS_OUTPUT), GetChaosString(MSG_NAME_OUTPUT),
  682.       GetChaosString(MSG_GAME_OUTPUT));
  683.   TabFirst = MakeTable(sortmode);
  684.  
  685.   lines = (NumRounds+3)/8+1;
  686.   if (!InitOutput(title, head, head, filename, "#?.tblp", device, lines,
  687.           lines))
  688.   { TerminateOutput();
  689.     return;
  690.   }
  691.  
  692.   for (t = TabFirst, i = 0;  t != NULL;  t = t->Helpptr)
  693.   { t->Nr = ++i;
  694.   }
  695.  
  696.   for (t = TabFirst;  t != NULL;  t = t->Helpptr)
  697.   { PointsToA(pointsstr, (long) t->Points);
  698.     sprintf(line, "%4d %6s %-34s", t->Nr, pointsstr, t->Name);
  699.     gperline = 3;
  700.     for (i = 1;  i <= NumRounds;  i++)
  701.     { needprint = TRUE;
  702.       g = GameAddress(t, i);
  703.       if (g->Flags & GMFLAGSF_POINTFORFREE)
  704.       { sprintf(helps, (char *) GetChaosString(MSG_FREE_GAME_OUTPUT));
  705.       }
  706.       else if (g->Flags & GMFLAGSF_WITHDRAWN)
  707.       { sprintf(helps, (char *) GetChaosString(MSG_GONE_OUTPUT));
  708.       }
  709.       else
  710.       { static char *ergchars = "?-=+";
  711.     sprintf(helps, "  %4d%c%c%c", g->Opponent->Nr,
  712.         ergchars[g->Result+1],
  713.         (g->Flags&GMFLAGSF_WHITE) ? 'w' : 's',
  714.         (g->Flags&GMFLAGSF_NOFIGHT) ? 'k' : ' ');
  715.       }
  716.       strcat(line, helps);
  717.       if (--gperline == 0)
  718.       { if (!lprint(line))
  719.     { TerminateOutput();
  720.       return;
  721.     }
  722.     gperline = 7;
  723.     sprintf(line, "          ");
  724.     needprint = FALSE;
  725.       }
  726.     }
  727.     if (needprint)
  728.     { if (!lprint(line))
  729.       { TerminateOutput();
  730.     return;
  731.       }
  732.     }
  733.   }
  734.  
  735.   ProcessOutput();
  736.   TerminateOutput();
  737. }
  738.  
  739.  
  740.  
  741.  
  742. /*
  743.     The cross table can be printed on screen, on printer in ascii format
  744.     or in TeX format. Note, that this must not be called in a Swiss Pairing
  745.     tournament! Strange things might happen!
  746.  
  747.     Inputs: filename    - destination file; see InitOutput()
  748.         device    - output device; see InitOutput()
  749. */
  750. void OutCrossTable(char *filename, int device)
  751.  
  752. { struct Player *plr;
  753.   struct Player **plrlist;
  754.   void *PlrMem = NULL;
  755.   struct Game *gm;
  756.   char *title;
  757.   int i,j;
  758.   char line[512];
  759.   char subline[512];
  760.   int allflag;
  761.   int width;
  762.  
  763.   /*
  764.       Create the player table. (We deal with player numbers here and so its
  765.       easier to use the table instead of going through the list of players
  766.       each time.)
  767.   */
  768.   if ((plrlist = GetMem(&PlrMem, sizeof(struct Player *)*NumPlayers))
  769.            ==  NULL)
  770.   { return;
  771.   }
  772.   for (plr = (struct Player *) PlayerList.lh_Head;
  773.        plr->Tn_Node.ln_Succ != NULL;
  774.        plr = (struct Player *) plr->Tn_Node.ln_Succ)
  775.   { plrlist[plr->Nr-1] = plr;
  776.   }
  777.  
  778.  
  779.  
  780.   if (device == DEVICE_FileTeX)
  781.   { title = "";
  782.   }
  783.   else
  784.   { title = (char *) GetChaosString(MSG_OUTPUT_CROSSTABLE_ITEM);
  785.   }
  786.   if (!InitOutput(title, "", "", filename, "#?.crss", device, 0, 0))
  787.   { goto Terminate;
  788.   }
  789.  
  790.  
  791.   /*
  792.       Some guys (me!) like beautiful TeX printings...
  793.   */
  794.   if (device == DEVICE_FileTeX)
  795.   { sprintf(line, "\\documentstyle[german,a4,%s]{article}\n"
  796.           "\\newcommand{\\r}{$\\frac{1}{2}$}\n"
  797.           "\\renewcommand{\\arraystretch}{2.0}\n"
  798.           "\\parindent0em\n\n"
  799.           "\\begin{document}\n"
  800.           "  \\begin{tabular}{l|*{%d}{p{0.6cm}|}r}",
  801.           (NumPlayers < 25) ? "12pt" : "",
  802.           NumPlayers);
  803.     if (!longlprint(line))
  804.     { goto Terminate;
  805.     }
  806.  
  807.     strcpy(line, "    ");
  808.     for (i = 0;  i < NumPlayers;  i++)
  809.       { sprintf(line + strlen(line), "& %d ", i+1);
  810.       }
  811.     strcat(line, "& \\\\\\hline");
  812.     if (!lprint(line))
  813.     { goto Terminate;
  814.     }
  815.  
  816.  
  817.     for (i = 1;  i <= NumPlayers;  i++)
  818.     { plr = plrlist[i-1];
  819.       sprintf(line, "    %s", plr->Name);
  820.       allflag = TRUE;
  821.       for (j = 1;  j <= NumPlayers;  j++)
  822.       { if (j == i)
  823.     { strcat(line, "& x ");
  824.     }
  825.     else
  826.     { gm = plr->First_Game;
  827.       while(gm->Opponent == NULL  ||  gm->Opponent->Nr != j)
  828.       { gm = gm->Next;
  829.       }
  830.       switch (gm->Result)
  831.       { case 2:
  832.           strcat(line, "& 1 ");
  833.           break;
  834.         case 1:
  835.           strcat(line, "& \\r");
  836.           break;
  837.         case 0:
  838.           strcat(line, "& 0 ");
  839.           break;
  840.         default:
  841.           strcat(line, "&   ");
  842.           allflag = FALSE;
  843.       }
  844.     }
  845.       }
  846.       strcat(line, "& ");
  847.       if (allflag)
  848.       { PointsToA(line+strlen(line), (long) plr->Points);
  849.       }
  850.       if (i < NumPlayers)
  851.       { strcat(line, "\\\\\\hline");
  852.       }
  853.       if (!lprint(line))
  854.       { goto Terminate;
  855.       }
  856.     }
  857.  
  858.     if (!longlprint("  \\end{tabular}\n"
  859.             "\\end{document}"))
  860.     { goto Terminate;
  861.     }
  862.   }
  863.  
  864.   /*
  865.       other guys don't have or don't like TeX (really? :-( ) For those
  866.       poor creatures the Ascii output:
  867.   */
  868.   else
  869.   { CenterText(device);
  870.  
  871.     if (NumPlayers < 10)
  872.     { width = 40 + NumPlayers*4;
  873.     }
  874.     else
  875.     { width = 40 + NumPlayers*2;
  876.     }
  877.     for (i = 0;  i < width;  i++)
  878.     { subline[i] = '-';
  879.     }
  880.     subline[width] = '\0';
  881.  
  882.     if (NumPlayers > 99)
  883.     { sprintf(line, "%36s|", "");
  884.       for (i = 1;  i <= NumPlayers;  i++)
  885.       { plr = plrlist[i-1];
  886.     if (i > 99)
  887.     { sprintf(line + strlen(line), "%c|", i/100+'0');
  888.     }
  889.     else
  890.     {strcat(line, " |");
  891.     }
  892.       }
  893.       if (!lprint(line))
  894.       { goto Terminate;
  895.       }
  896.     }
  897.  
  898.  
  899.     if (NumPlayers > 9)
  900.     { sprintf(line, "%36s|", "");
  901.       for (i = 1;  i <= NumPlayers;  i++)
  902.       { plr = plrlist[i-1];
  903.     if (i > 9)
  904.     { sprintf(line + strlen(line), "%c|", (i%100)/10+'0');
  905.     }
  906.     else
  907.     { strcat(line, " |");
  908.     }
  909.       }
  910.       if (!lprint(line))
  911.       { goto Terminate;
  912.       }
  913.     }
  914.  
  915.  
  916.     sprintf(line, "%36s|", "");
  917.     for (i = 1;  i <= NumPlayers;  i++)
  918.     { plr = plrlist[i-1];
  919.       sprintf(line + strlen(line), (NumPlayers > 9) ? "%c|" : " %c |",
  920.           i%10+'0');
  921.     }
  922.     if (!lprint(line))
  923.     { goto Terminate;
  924.     }
  925.  
  926.  
  927.     for (i = 1;  i <= NumPlayers;  i++)
  928.     { plr = plrlist[i-1];
  929.  
  930.       sprintf(line, "|%3d %30s |", i, plr->Name);
  931.       allflag = TRUE;
  932.  
  933.       for (j = 1;  j <= NumPlayers;  j++)
  934.       { if (j == i)
  935.     { strcat(line, (NumPlayers > 9) ? "x|" : " x |");
  936.     }
  937.     else
  938.     { static const char *ergs = {" 0=1" };
  939.  
  940.       gm = plr->First_Game;
  941.       while(gm->Opponent == NULL  ||  gm->Opponent->Nr != j)
  942.       { gm = gm->Next;
  943.       }
  944.  
  945.       sprintf(line+strlen(line), (NumPlayers > 9) ? "%c|" : " %c |",
  946.           ergs[gm->Result+1]);
  947.       if (gm->Result == -1)
  948.       { allflag = FALSE;
  949.       }
  950.     }
  951.       }
  952.       if (allflag)
  953.       { PointsToA(line + strlen(line), (long) plr->Points);
  954.       }
  955.       if (!lprint(subline)  ||  !lprint(line))
  956.       { goto Terminate;
  957.       }
  958.     }
  959.   }
  960.  
  961.   ProcessOutput();
  962.  
  963. Terminate:
  964.   TerminateOutput();
  965.   PutMemList(&PlrMem);
  966. }
  967.  
  968.  
  969.  
  970.  
  971. /*
  972.     The following function prints the player cards.
  973.  
  974.     Inputs: filename - destination file; see InitOutput()
  975.         device   - output device; see InitOutput()
  976. */
  977. void OutPlayerCards(char *filename, int device)
  978.  
  979. { struct Player *plr, **plrlist;
  980.   void *PlrMem = NULL;
  981.   struct Game *gm;
  982.   int i, j;
  983.   int defrounds, numrounds;
  984.   int lines;
  985.   char line[512];
  986.   char subline[512];
  987.   char *title;
  988.  
  989.   /*
  990.       Create the player table. (We deal with player numbers here and so its
  991.       easier to use the table instead of going through the list of players
  992.       each time.)
  993.   */
  994.   if ((plrlist = GetMem(&PlrMem, sizeof(struct Player *)*NumPlayers))
  995.            ==  NULL)
  996.   { return;
  997.   }
  998.   for (i = 0, plr = (struct Player *) PlayerList.lh_Head;
  999.        plr->Tn_Node.ln_Succ != NULL;
  1000.        plr = (struct Player *) plr->Tn_Node.ln_Succ)
  1001.   { plrlist[i++] = plr;
  1002.     plr->Nr = i;
  1003.   }
  1004.  
  1005.  
  1006.   /*
  1007.       Determine, how much rounds to print
  1008.   */
  1009.   defrounds = (device == DEVICE_FileTeX) ? 11 : 9;
  1010.   if (NumRounds < defrounds-1)
  1011.   { numrounds = defrounds;
  1012.   }
  1013.   else
  1014.   { numrounds = NumRounds+2;
  1015.   }
  1016.   if ((numrounds % 2) == 0)
  1017.   { numrounds++;
  1018.   }
  1019.  
  1020.   if (device == DEVICE_FileTeX)
  1021.   { title = "";
  1022.     lines = 0;
  1023.   }
  1024.   else
  1025.   { title = (char *) GetChaosString(MSG_OUTPUT_PLAYERCARDS_ITEM);
  1026.     lines = 11;
  1027.   }
  1028.   if (!InitOutput(title, "", "", filename, "#?.pcrd", device, lines, lines))
  1029.   { goto Terminate;
  1030.   }
  1031.  
  1032.   /*
  1033.       Some guys (me!) like beautiful TeX printings...
  1034.   */
  1035.   if (device == DEVICE_FileTeX)
  1036.   { sprintf(line, "\\documentstyle[german,a4,12pt]{article}\n"
  1037.           "\\renewcommand{\\arraystretch}{2.0}\n"
  1038.           "\\parindent0em\n\n"
  1039.           "\\begin{document}");
  1040.     if (!longlprint(line))
  1041.     { goto Terminate;
  1042.     }
  1043.  
  1044.     for (plr = (struct Player *) PlayerList.lh_Head;
  1045.      plr->Tn_Node.ln_Succ != NULL;
  1046.      plr = (struct Player *) plr->Tn_Node.ln_Succ)
  1047.     { sprintf(line, "\\begin{tabular}{|l*{%d}{|p{0.6cm}}|}\\hline\n"
  1048.             "%s %d&\\multicolumn{%d}{|l|}{%s}\\\\\\hline",
  1049.           numrounds, GetChaosString(MSG_NUMBER),
  1050.           plr->Nr, numrounds, plr->Name);
  1051.       if (!longlprint(line))
  1052.       { goto Terminate;
  1053.       }
  1054.  
  1055.       strcpy(line, (char *) GetChaosString(MSG_WHITE_OUTPUT));
  1056.       for (j = 0, gm = plr->First_Game;  j < numrounds;  j++)
  1057.       { if (gm != NULL)
  1058.     { if (gm->Flags & GMFLAGSF_WHITE)
  1059.       { sprintf(line + strlen(line), "&%d", gm->Opponent->Nr);
  1060.       }
  1061.       else
  1062.       { sprintf(line + strlen(line),
  1063.             (gm->Flags & GMFLAGSF_POINTFORFREE) ? "&%s" : "&",
  1064.             GetChaosString(MSG_ONEPOINTBYE_VERYSHORT));
  1065.       }
  1066.       gm = gm->Next;
  1067.     }
  1068.     else
  1069.     { strcat(line, "&");
  1070.     }
  1071.       }
  1072.       strcat(line, "\\\\\\hline");
  1073.       if (!lprint(line))
  1074.       { goto Terminate;
  1075.       }
  1076.  
  1077.       strcpy(line, (char *) GetChaosString(MSG_BLACK_OUTPUT));
  1078.       for (j = 0, gm = plr->First_Game;  j < numrounds;  j++)
  1079.       { if (gm != NULL)
  1080.     { if ((gm->Flags & (GMFLAGSF_WHITE|GMFLAGSF_POINTFORFREE))  ==  0)
  1081.       { sprintf(line + strlen(line), "&%d", gm->Opponent->Nr);
  1082.       }
  1083.       else
  1084.       { sprintf(line + strlen(line),
  1085.             (gm->Flags & GMFLAGSF_POINTFORFREE) ? "&%s" : "&",
  1086.             GetChaosString(MSG_ONEPOINTBYE_VERYSHORT));
  1087.       }
  1088.       gm = gm->Next;
  1089.     }
  1090.     else
  1091.     { strcat(line, "&");
  1092.     }
  1093.       }
  1094.       strcat(line, "\\\\\\hline");
  1095.       if (!lprint(line))
  1096.       { goto Terminate;
  1097.       }
  1098.  
  1099.       strcpy(line, (char *) GetChaosString(MSG_POINTS_OUTPUT));
  1100.       for (j = 0, i = 0, gm = plr->First_Game;  j < numrounds;  j++)
  1101.       { strcat(line, "&");
  1102.     if (gm != NULL)
  1103.     { i += gm->Result;
  1104.       gm = gm->Next;
  1105.       PointsToA(line + strlen(line), (long) i);
  1106.     }
  1107.       }
  1108.       strcat(line, "\\\\\\hline\n"
  1109.            "\\end{tabular}\n\n\\vspace{0.5cm}\n");
  1110.       if (!longlprint(line))
  1111.       { goto Terminate;
  1112.       }
  1113.     }
  1114.     if (!lprint("\\end{document}"))
  1115.     { goto Terminate;
  1116.     }
  1117.   }
  1118.  
  1119.   /*
  1120.       other guys don't have or don't like TeX (really? :-( ) For those
  1121.       poor creatures the Ascii output:
  1122.   */
  1123.   else
  1124.   { char *plrformatstr, *emptyformatstr, *onepbyeformatstr, *pointsformatstr;
  1125.     char ppointsstr[10];
  1126.     int width, plrwidth;
  1127.  
  1128.     CenterText(device);
  1129.  
  1130.     if (numrounds > 11)
  1131.     { plrformatstr = "%3d |";
  1132.       emptyformatstr = "    |";
  1133.       onepbyeformatstr = "  %s |";
  1134.       pointsformatstr = "%4s";
  1135.       plrwidth = 4;
  1136.     }
  1137.     else
  1138.     { plrformatstr = " %3d |";
  1139.       emptyformatstr = "     |";
  1140.       onepbyeformatstr = "  %s  |";
  1141.       pointsformatstr = "%4s |";
  1142.       plrwidth = 6;
  1143.     }
  1144.     width = 14 + (numrounds+1) * plrwidth;
  1145.     for (i = 0;  i < width;  i++)
  1146.     { subline[i] = '-';
  1147.     }
  1148.     subline[width] = '\0';
  1149.  
  1150.  
  1151.     for (plr = (struct Player *) PlayerList.lh_Head;
  1152.      plr->Tn_Node.ln_Succ != NULL;
  1153.      plr = (struct Player *) plr->Tn_Node.ln_Succ)
  1154.     { if (!lprint(subline))
  1155.       { goto Terminate;
  1156.       }
  1157.  
  1158.       sprintf(line, "| %4s  %4d | %30s",
  1159.           GetChaosString(MSG_NUMBER), plr->Nr, plr->Name);
  1160.       for (i = strlen(line);  i < width-1;  i++)
  1161.       { line[i] = ' ';
  1162.       }
  1163.       line[width-1] = '|';
  1164.       line[width] = '\0';
  1165.       if (!lprint(line))
  1166.       { goto Terminate;
  1167.       }
  1168.  
  1169.       if (!lprint(subline))
  1170.       { goto Terminate;
  1171.       }
  1172.  
  1173.       sprintf(line, "| %10s |", (char *) GetChaosString(MSG_WHITE_OUTPUT));
  1174.       for (j = 0, gm = plr->First_Game;  j < numrounds+1;  j++)
  1175.       { if (gm != NULL)
  1176.     { if (gm->Flags & GMFLAGSF_WHITE)
  1177.       { sprintf(line + strlen(line), plrformatstr, gm->Opponent->Nr);
  1178.       }
  1179.       else
  1180.       { sprintf(line + strlen(line),
  1181.             (gm->Flags & GMFLAGSF_POINTFORFREE) ?
  1182.                 onepbyeformatstr : emptyformatstr,
  1183.             GetChaosString(MSG_ONEPOINTBYE_VERYSHORT));
  1184.       }
  1185.       gm = gm->Next;
  1186.     }
  1187.     else
  1188.     { strcat(line, emptyformatstr);
  1189.     }
  1190.       }
  1191.       if (!lprint(line)  ||  !lprint(subline))
  1192.       { goto Terminate;
  1193.       }
  1194.  
  1195.       sprintf(line, "| %10s |", (char *) GetChaosString(MSG_BLACK_OUTPUT));
  1196.       for (j = 0, gm = plr->First_Game;  j < numrounds+1;  j++)
  1197.       { if (gm != NULL)
  1198.     { if ((gm->Flags & (GMFLAGSF_WHITE|GMFLAGSF_POINTFORFREE))  ==  0)
  1199.       { sprintf(line + strlen(line), plrformatstr, gm->Opponent->Nr);
  1200.       }
  1201.       else
  1202.       { sprintf(line + strlen(line),
  1203.             (gm->Flags & GMFLAGSF_POINTFORFREE) ?
  1204.                 onepbyeformatstr : emptyformatstr,
  1205.             GetChaosString(MSG_ONEPOINTBYE_VERYSHORT));
  1206.       }
  1207.       gm = gm->Next;
  1208.     }
  1209.     else
  1210.     { strcat(line, emptyformatstr);
  1211.     }
  1212.       }
  1213.       if (!lprint(line)  ||  !lprint(subline))
  1214.       { goto Terminate;
  1215.       }
  1216.  
  1217.       sprintf(line, "| %10s |", (char *) GetChaosString(MSG_POINTS_OUTPUT));
  1218.       for (j = 0, i = 0, gm = plr->First_Game;  j < numrounds+1;  j++)
  1219.       { if (gm != NULL)
  1220.     { i += gm->Result;
  1221.       gm = gm->Next;
  1222.       PointsToA(ppointsstr, (long) i);
  1223.       sprintf(line + strlen(line), pointsformatstr, ppointsstr);
  1224.     }
  1225.     else
  1226.     { strcat(line, emptyformatstr);
  1227.     }
  1228.       }
  1229.       if (!lprint(line) ||  !lprint(subline)  ||  !lprint("\n"))
  1230.       { goto Terminate;
  1231.       }
  1232.     }
  1233.   }
  1234.  
  1235.   ProcessOutput();
  1236.  
  1237. Terminate:
  1238.   TerminateOutput();
  1239.   PutMemList(&PlrMem);
  1240. }
  1241.